/*
 * Copyright (C) 2021 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a  copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.luseen.verticalintrolibrary;

import com.luseen.verticalintro.ResourceTable;
import ohos.aafwk.ability.AbilitySlice;
import ohos.aafwk.content.Intent;
import ohos.agp.animation.AnimatorValue;
import ohos.agp.colors.RgbColor;
import ohos.agp.components.*;
import ohos.agp.components.element.ShapeElement;
import ohos.agp.text.Font;
import ohos.agp.utils.Color;
import ohos.agp.window.dialog.ToastDialog;
import ohos.agp.window.service.WindowManager;
import ohos.app.Environment;
import ohos.global.resource.RawFileEntry;
import ohos.global.resource.Resource;
import ohos.global.resource.ResourceManager;
import ohos.multimodalinput.event.TouchEvent;
import ohos.vibrator.agent.VibratorAgent;
import ohos.vibrator.bean.VibrationPattern;

import java.io.*;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;

public class VerticalIntroSlice extends AbilitySlice implements PageSlider.PageChangedListener, Component.TouchEventListener {
    public List<String> pageColors;
    public List<VerticalIntroItem> pageMoudles = new ArrayList<>();
    private int page = 0;
    private HmButton skip;
    private Button next;
    private PageSlider pageSlider;
    private PageSlider pageSliderBg;
    private double startPointY;
    private double movePointY;
    private int nextHeight;
    private VerticalIntroPagerAdapter adapter;
    private ToastDialog toastDialog;
    private int slideState;
    private boolean isSkipEnabled = true;
    private boolean isVibrateEnabled = true;
    private int vibrateIntensity = 20;
    private int skipColor = 0;
    private String nextText = "NEXT";
    private String doneText = "DONE";
    private String skipText = "SKIP";
    private Font customFont = null;


    @Override
    public void onStart(Intent intent) {
        super.onStart(intent);
        super.setUIContent(ResourceTable.Layout_vertical_intro_ability);
        initView();
        setData();
        initTitleColors();
        initPageSlider();
    }

    public void setData() {
    }


    protected void setSkipEnabled(boolean skipEnabled) {
        isSkipEnabled = skipEnabled;
    }
    protected void setVibrateEnabled(boolean vibrateEnabled) {
        isVibrateEnabled = vibrateEnabled;
    }
    public void setVibrateIntensity(int vibrateIntensity) {
        this.vibrateIntensity = vibrateIntensity;
    }
    public void setSkipColor(int skipColor) {
        this.skipColor = skipColor;
    }
    public void setNextText(String nextText) {
        this.nextText = nextText;
    }
    public void setDoneText(String doneText) {
        this.doneText = doneText;
    }
    public void setSkipText(String skipText) {
        this.skipText = skipText;
    }
    protected void setCustomTypeFace(String fontPath) {
        ResourceManager resManager = getContext().getResourceManager();
        RawFileEntry rawFileEntry = resManager.getRawFileEntry(fontPath);
        Resource resource = null;
        try {
            resource = rawFileEntry.openRawFile();
        } catch (IOException e) {
            e.printStackTrace();
        }
        StringBuffer fileName = new StringBuffer(fontPath.substring(fontPath.lastIndexOf("/"))+1);

        File file = new File(getContext().getExternalFilesDir(Environment.DIRECTORY_PICTURES), fileName.toString());
        OutputStream outputStream = null;
        try {
            outputStream = new FileOutputStream(file);
            int index;
            byte[] bytes = new byte[1024];
            if (resource != null) {
                while ((index = resource.read(bytes)) != -1) {
                    outputStream .write(bytes, 0, index);
                    outputStream .flush();
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (resource != null) {
                    resource.close();
                }
                if (outputStream != null) {
                    outputStream.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        Font.Builder builder = new Font.Builder(file);
        customFont = builder.build();
    }

    protected void addIntroItem(VerticalIntroItem verticalIntroItem) {
        pageMoudles.add(verticalIntroItem);
    }

    private void initView() {
        pageSlider = (PageSlider) findComponentById(ResourceTable.Id_vertical_view_pager);
        skip = (HmButton) findComponentById(ResourceTable.Id_skip);
        next = (Button) findComponentById(ResourceTable.Id_next);
        pageSliderBg = (PageSlider) findComponentById(ResourceTable.Id_vertical_view_pager_bg);
        pageSliderBg.setOrientation(Component.VERTICAL);
        nextHeight = 180;
        skip.setClickedListener(component -> {
            clickVibrate();
            page = 3;
            pageSlider.setCurrentPage(3);
            skip.setVisibility(Component.INVISIBLE);
            next.setText(doneText);
        });
        next.setClickedListener(component -> {
            clickVibrate();
            if (page != pageColors.size() - 1) {
                pageSlider.setCurrentPage(page + 1);
            } else if (pageSlider.getCurrentPage() == 3) {
                toastShow();
                skip.setVisibility(Component.INVISIBLE);
                next.setText(doneText);
            }
        });
    }

    private void clickVibrate(){
        if(isVibrateEnabled){
            VibratorAgent vibratorAgent=new VibratorAgent();
            vibratorAgent.start(VibrationPattern.createSingle(50,vibrateIntensity));
        }
    }

    private void initTitleColors() {
        if (isSkipEnabled) {
            skip.setVisibility(Component.VISIBLE);
        } else {
            skip.setVisibility(Component.HIDE);
        }

        if(skipColor!=0){
            skip.setTextColor(new Color(skipColor));
        }

        skip.setText(skipText);
        next.setText(nextText);

        if(customFont!=null){
            skip.setFont(customFont);
            next.setFont(customFont);
        }

        WindowManager.getInstance().getTopWindow().get().setStatusBarColor(getColorByString(pageColors.get(page)));
        next.setTouchEventListener(new Component.TouchEventListener() {
            @Override
            public boolean onTouchEvent(Component component, TouchEvent touchEvent) {
                pageSlider.setSlidingPossible(false);
                return true;
            }
        });

        List<String> listBgColor = new ArrayList<>(pageColors);
        if (listBgColor.size() > 0) {
            String firstColor = listBgColor.remove(0);
            listBgColor.add(firstColor);
            listBgColor.remove(listBgColor.size() - 1);
            String secondColor = listBgColor.get(0);
            listBgColor.add(secondColor);
        }

        pageSliderBg.setProvider(new PageSliderProvider() {
            @Override
            public int getCount() {
                return listBgColor.size();
            }

            @Override
            public Object createPageInContainer(ComponentContainer componentContainer, int i) {
                Component component = new Component(getContext());
                ShapeElement shapeElement = new ShapeElement();
                shapeElement.setRgbColor(RgbColor.fromArgbInt(Color.getIntColor(listBgColor.get(i))));
                component.setBackground(shapeElement);
                componentContainer.addComponent(component);
                return component;
            }

            @Override
            public void destroyPageFromContainer(ComponentContainer componentContainer, int i, Object o) {
                componentContainer.removeComponent((Component) o);
            }

            @Override
            public boolean isPageMatchToObject(Component component, Object o) {
                return true;
            }
        });

    }

    private int getColorByString(String color) {
        return Color.getIntColor(color);
    }

    private void initPageSlider() {
        pageSlider.setOrientation(Component.VERTICAL);
        pageSlider.addPageChangedListener(this);
        pageSlider.setTouchEventListener(this::onTouchEvent);
        adapter = new VerticalIntroPagerAdapter(this, pageMoudles,customFont);
        pageSlider.setProvider(adapter);
    }

    @Override
    public void onActive() {
        super.onActive();
    }

    @Override
    public void onForeground(Intent intent) {
        super.onForeground(intent);
    }

    @Override
    public void onPageSliding(int index, float v, int i1) {
        if (v == 1 || v == 0 && page == index) {
            WindowManager.getInstance().getTopWindow().get().setStatusBarColor(getColorByString(pageColors.get(page)));
            Image image1 = (Image) adapter.pageComonents.get(pageSlider.getCurrentPage())
                    .findComponentById(ResourceTable.Id_sliderImage);
            image1.setAlpha(1.0f);
            Text title1 = (Text) adapter.pageComonents.get(pageSlider.getCurrentPage())
                    .findComponentById(ResourceTable.Id_title);
            title1.setAlpha(1.0f);
            Text text1 = (Text) adapter.pageComonents.get(pageSlider.getCurrentPage())
                    .findComponentById(ResourceTable.Id_text);
            text1.setAlpha(1.0f);
        }

        if(v > 0.6 && slideState==2){
            pageSliderBg.setCurrentPage(page);
        }

        if (movePointY > 0) {
            setPageApale(index, index - 1, v);
        }
        if (movePointY < 0) {
            setPageApale(index, index + 1, v);
        }
    }

    private void setPageApale(int currentPage, int targetPage, float offset) {
        if (adapter.pageComonents != null && adapter.pageComonents.get(currentPage) != null
                && adapter.pageComonents.get(targetPage) != null) {
            float alpha = new BigDecimal(1.0f).subtract(new BigDecimal(offset).multiply(new BigDecimal(2))).floatValue();
            if (offset >= 0.4 && offset <= 0.9) {
                offset = new BigDecimal(offset).subtract(new BigDecimal(0.4f)).floatValue();
            } else if (offset < 0.4) {
                offset = 0.0f;
            } else {
                offset = 1.0f;
            }
            setApale(currentPage, targetPage, alpha, offset);
        }
    }

    private void setApale(int currentPage, int targetPage, float alpha, float offset) {
        Image image = (Image) adapter.pageComonents.get(currentPage)
                .findComponentById(ResourceTable.Id_sliderImage);
        image.setAlpha(alpha);
        Image image1 = (Image) adapter.pageComonents.get(targetPage)
                .findComponentById(ResourceTable.Id_sliderImage);
        image1.setAlpha(offset);
        Text title = (Text) adapter.pageComonents.get(currentPage).findComponentById(ResourceTable.Id_title);
        title.setAlpha(alpha);
        Text title1 = (Text) adapter.pageComonents.get(targetPage).findComponentById(ResourceTable.Id_title);
        title1.setAlpha(offset);
        Text text = (Text) adapter.pageComonents.get(currentPage).findComponentById(ResourceTable.Id_text);
        text.setAlpha(alpha);
        Text text1 = (Text) adapter.pageComonents.get(targetPage).findComponentById(ResourceTable.Id_text);
        text1.setAlpha(offset);
    }


    @Override
    public void onPageSlideStateChanged(int index) {
        slideState = index;
    }

    Timer timer;
    @Override
    protected void onStop() {
        super.onStop();
        timer.cancel();
    }

    @Override
    public void onPageChosen(int index) {
        System.out.println(page+"=page=============index="+index);
        if (index == pageColors.size()-1) {
            if (isSkipEnabled) {
                skip.setVisibility(Component.INVISIBLE);
            }
            next.setText(doneText);
            next.setVisibility(Component.INVISIBLE);
            timer = new Timer();
            timer.schedule(new TimerTask() {
                @Override
                public void run() {
                    getContext().getUITaskDispatcher().syncDispatch(() -> {
                        next.setVisibility(Component.VISIBLE);
                    });
                }
            }, 50);

        } else {
            if (isSkipEnabled) {
                skip.setVisibility(Component.VISIBLE);
            }
            next.setText(nextText);
            if (page == pageColors.size() - 1 && index == pageColors.size() - 2) {
                next.setVisibility(Component.INVISIBLE);
                timer = new Timer();
                timer.schedule(new TimerTask() {
                    @Override
                    public void run() {
                        getContext().getUITaskDispatcher().syncDispatch(() -> {
                            next.setVisibility(Component.VISIBLE);
                        });
                    }
                }, 50);
            }
        }
        page = index;
    }

    private void toastShow() {
        if (toastDialog == null) {
            toastDialog = new ToastDialog(getContext());
        }
        toastDialog.setText("DONE");
        toastDialog.setOffset(0, nextHeight);
        toastDialog.setSize(200, 80);
        toastDialog.show();
    }

    @Override
    public boolean onTouchEvent(Component component, TouchEvent touchEvent) {
        int action = touchEvent.getAction();
        switch (action) {
            case TouchEvent.PRIMARY_POINT_DOWN:
                pageSlider.setSlidingPossible(true);
                startPointY = getTouchY(touchEvent, 0, component);
                return true;
            case TouchEvent.POINT_MOVE:
                movePointY = getTouchY(touchEvent, touchEvent.getIndex(), component) - startPointY;
                if (page != 0 && movePointY > 0) {
                    WindowManager.getInstance().getTopWindow().get().setStatusBarColor(getColorByString(pageColors.get(page - 1)));
                }
                return true;
            case TouchEvent.PRIMARY_POINT_UP:
                return true;
            default:
        }
        return false;
    }


    private float getTouchY(TouchEvent touchEvent, int index, Component component) {
        double touchY = 0;
        if (touchEvent.getPointerCount() > index) {
            int[] xy = component.getLocationOnScreen();
            if (xy != null && xy.length == 2) {
                touchY = (double) touchEvent.getPointerScreenPosition(index).getY() - xy[1];
            } else {
                touchY = touchEvent.getPointerPosition(index).getY();
            }
        }
        return (float) touchY;
    }
}
